package org.lgiavedoni.android.franq.service.cron;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;

import org.lgiavedoni.android.franq.core.cron.CronTask;
import org.lgiavedoni.android.franq.core.service.Service;
import org.lgiavedoni.android.franq.service.log.Logger;
import org.lgiavedoni.android.franq.util.classU.ClassUtil;
import org.lgiavedoni.android.franq.util.collection.CollectionUtils;
import org.lgiavedoni.android.franq.util.implementation.Implementation;
import org.lgiavedoni.android.franq.util.implementation.ImplementationUtil;
import org.lgiavedoni.android.franq.util.timer.TimerUtil;

public class CronService extends Service {

	public static final CronService inst = new CronService();
	private List<Implementation> cronsImp = new ArrayList<Implementation>();
	private final List<CronTask> crons = new ArrayList<CronTask>();
	private final Timer cronTimer = new Timer();

	@Override
	public String getServiceName() {
		return "cron";
	}

	public CronService() {
		cronsImp = ImplementationUtil.getImplementations(CronTask.class);
	}

	@Override
	protected void startInternal() {
		/*
		 * crons.clear(); for (Object obj :
		 * ImplementationUtil.getImplementationsInst(CronTask.class)) { CronTask
		 * cron = (CronTask) obj; crons.add(cron); }
		 */
	}

	@Override
	public void _run() {
		crons.clear();
		CollectionUtils.setAll(ImplementationUtil.initialize(cronsImp), crons);
		for (CronTask cron : crons) {
			try {
				TimerUtil.addCron(cronTimer, cron);
			} catch (Exception ex) {
				Logger.inst.error(ex);
			}
		}
	}

	@Override
	protected void stopInternal() {
		for (CronTask cron : crons) {
			cron.cancel();
		}
		TimerUtil.purge(cronTimer);
		crons.clear();
	}

	public void removeCron(Class<? extends CronTask> cronClazz) {
		CronTask cron = null;
		for (CronTask c : crons) {
			if (ClassUtil.isInstanceOf(c.getClass(), cronClazz)) {
				cron = c;
				break;
			}
		}
		if (cron != null) {
			cron.cancel();
			crons.remove(cron);
			TimerUtil.purge(cronTimer);
			for (Implementation imp : cronsImp) {
				if (imp.getClazzName().equals(cronClazz.getCanonicalName())) {
					cronsImp.remove(imp);
				}
			}
		} else {
			Logger.inst.error("Con-existent cron job for class [" + cronClazz + "]");
		}
	}

	public void addCron(Class<? extends CronTask> cronClazz) {
		cronsImp.add(new Implementation(cronClazz.getCanonicalName()));

		CronTask cronTask;
		try {
			cronTask = cronClazz.newInstance();
			crons.add(cronTask);
			if (isStarted())
				TimerUtil.addCron(cronTimer, cronTask);
		} catch (Exception e) {
			Logger.inst.error(e);
		}

	}

	public List<CronTask> getCrons() {
		return crons;
	}

}
